import { parse } from 'qs';
import { routerRedux } from 'dva/router';
import { message } from 'antd';
import { login, loginCheck, init, validateToken } from '@/services/users';
import { bindMFA } from '@/services/authority';

import { reloadAuthorized } from '@/utils/Authorized';
import { authSite } from '../../config/defaultSettings';

const getPageQuery = () => parse(window.location.href.split('?')[1]);

const pageRedirect = data => {
  const { hasBindSecretKey = true, isNeedMfaCheek = false } = data;
  const params = getPageQuery();
  let { redirect } = params;
  redirect = redirect || '/#/center';
  if (!hasBindSecretKey) {
    redirect = `/#/center/mfa?redirect=${redirect}`;
  }
  if (!isNeedMfaCheek) {
    window.location.replace(redirect);
  }

  // 登陆之后需要重定向
  // if (/^http(s)?:\/\//.test(redirect)) {
  //   const { location: winLocation } = window;
  //   const redirectURL = new URL(redirect);
  //   if (redirectURL.origin + redirectURL.pathname === winLocation.origin + winLocation.pathname) {
  //     redirect = redirectURL.hash.length > 0 ? redirectURL.hash.substr(1) : '/admin';
  //   }
  // } else {
  //   redirect = redirect || '/center';
  // }
  // if (!hasBindSecretKey) {
  //   redirect = `/center/mfa?redirect=${redirect}`;
  // }
  // if (!isNeedMfaCheek) {
  //   if (/^http(s)?:\/\//.test(redirect)) {
  //     window.location.replace(redirect);
  //   } else {
  //     router.replace(redirect);
  //     // yield put(routerRedux.replace(redirect));
  //   }
  // }
  // return redirect;
};

const isCrossDomain = () => {
  const { location } = window;
  const authUrl = authSite && authSite.homeUrl ? new URL(authSite.homeUrl) : location;
  return authUrl.origin !== location.origin;
};

const crossGetToken = () => {
  const iframe = document.createElement('iframe');
  iframe.src = `${authSite.homeUrl}/blank`;
  iframe.style.display = 'none';
  const reciveToken = resolve => event => {
    const { type = '', token = '' } = event.data;
    if (type === 'setToken') {
      // eslint-disable-next-line no-console
      console.log('%c crossDomain-Token', 'color:green', event.data);
      resolve(token);
    }
  };
  const promise = new Promise(resolve => {
    window.addEventListener('message', reciveToken(resolve), false);
  });
  document.body.appendChild(iframe);
  return promise;
};

async function getTokenStore() {
  let userToken = getToken();
  if (!userToken && isCrossDomain()) {
    userToken = await crossGetToken();
    if (userToken) {
      setToken(userToken);
    } else {
      toLoginPage('notoken');
    }
  }
  return userToken;
}

function getToken() {
  return localStorage.getItem('token');
}
function setToken(tokenStr) {
  localStorage.setItem('token', tokenStr);
}
function removeToken() {
  localStorage.removeItem('token');
}

function toLoginPage(type) {
  setTimeout(() => {
    const { location } = window;
    const { href } = location;
    const params = href.split('redirect=');
    const redirect = decodeURIComponent(params.length === 1 ? params[0] : params[params.length - 1]);
    const codeUrl = encodeURIComponent(redirect);
    location.replace(`#/user/login?type=${type}&redirect=${codeUrl}`);
  }, 0);
}

const Model = {
  namespace: 'login',
  state: {
    // userId: undefined,
    // username: undefined,
    // accessToken: undefined,
    // refreshToken: undefined,
    // isNeedMfaCheek: undefined,
    // hasBindSecretKey: undefined,
    // autoLogin: true,
    checkResult: false
  },

  effects: {
    //   登录
    *login({ payload }, { call, put }) {
      const { autoLogin, type } = payload;
      const response = yield call(login, payload);
      const { code, data = {} } = response || {};
      // Login successfully
      if (code === '000000') {
        const updateData = {
          ...response,
          type: 'update',
          data: {
            ...response.data,
            autoLogin,
            type
          }
        };
        yield put({ type: 'changeLoginStatus', payload: updateData });
        pageRedirect(data);
      }
      return response;
    },
    *bindSecret({ payload }, { call, put }) {
      const response = yield call(bindMFA, payload);
      const { data = false } = response || {};
      if (data) {
        const updateData = { type: 'update', data: { hasBindSecretKey: true } };
        yield put({ type: 'changeLoginStatus', payload: updateData });
        pageRedirect({ hasBindSecretKey: true });
      }
      return !!data;
    },
    *loginMFA({ payload }, { call, put }) {
      const response = yield call(loginCheck, payload);
      const { code, data = {} } = response || {};
      // checkResult
      const { checkResult } = data;
      if (checkResult) {
        const updateData = { ...response, type: 'update' };
        yield put({ type: 'changeLoginStatus', payload: updateData });
        pageRedirect(data);
      } else if (code === '000000') {
        message.error('动态验证码错误');
      } else {
        message.error(response.message || '验证失败');
      }
      return true;
    },
    // 用户初始化
    *init({ payload }, { call, put }) {
      const response = yield call(init, payload);
      const updateData = { ...response, type: 'update' };
      yield put({ type: 'changeLoginStatus', payload: updateData });
      // Login successfully
      if (response && response.code === '000000') {
        yield put({ ype: 'user/saveCurrentUser', payload: response });
        // 重新load权限路由页面
        reloadAuthorized();
        yield put(routerRedux.replace('/user/register-result'));
      }
      return response;
    },

    *logout(_, { put }) {
      // const response = yield call(loginOut);
      const initData = { type: 'init', data: { checkResult: false } };
      yield put({ type: 'changeLoginStatus', payload: initData });
      removeToken();
      reloadAuthorized();
      toLoginPage('logout');
    },

    *autoLogin(_, { call, put }) {
      const token = yield getTokenStore();
      if (!token) return null;
      try {
        const userToken = JSON.parse(token);
        const { accessToken } = userToken;
        const response = yield call(validateToken, { accessToken });
        const { code } = response || {};
        if (code !== '000000') {
          toLoginPage('valid-overdue');
        } else {
          const updateData = { type: 'update', data: JSON.parse(getToken()) };
          yield put({ type: 'changeLoginStatus', payload: updateData });
        }
        return userToken;
      } catch (error) {
        return null;
      }
    }
  },

  reducers: {
    changeLoginStatus(state, { payload }) {
      const { type = 'update', data = {} } = payload;
      const newState = type === 'update' ? { ...state, ...data } : { ...data };
      setToken(JSON.stringify(newState));
      return newState;
    }
  }
};

export default Model;
